/*
 * @Description:
 * @Version: 2.0
 * @Autor: xudongxu
 * @Date: 2020-03-27 15:19:05
 * @LastEditors: xudongxu
 * @LastEditTime: 2020-03-27 17:04:29
 */

#ifndef __MYAPPLICATION_H__
#define __MYAPPLICATION_H__

#include "task.hpp"
#include <Poco/FileChannel.h>
#include <Poco/FormattingChannel.h>
#include <Poco/LogFile.h>
#include <Poco/PatternFormatter.h>
#include <Poco/Poco.h>
#include <Poco/Util/Application.h>
#include <Poco/Util/HelpFormatter.h>
#include <Poco/Util/Option.h>
#include <Poco/Util/OptionSet.h>
#include <glog/logging.h>
#include <iostream>
#include <sys/stat.h>
#include <unistd.h>

using namespace Poco;

const std::string LOGHOME = "./log"; //日志目录
const std::string CONFIGHOME = "./config";

class MyApplication : public Util::Application {
public:
  MyApplication() { m_helpRequested = false; }
  void initialize(Application &self);
  void uninitialize();

  void defineOptions(Util::OptionSet &options);
  void handleHelp(const std::string &name, const std::string &value);
  void handleDaemon(const std::string &name, const std::string &value);
  int main(const std::vector<std::string> &args);

private:
  bool m_helpRequested; //如果传参数进来那么此变量变为 true 在main()
                        //方法就不要做其他的事情直接退出。
  void beDaemon();
};

void MyApplication::initialize(Application &self) {
  Util::Application::initialize(self); //帮我们初始化子系统，必须显示的调用。
  //初始化日志
  loadConfiguration("./config/config.ini");    
  auto logpath = Util::Application::config().getString("log.path");
  FLAGS_log_dir = logpath;
  google::InitGoogleLogging(self.argv().at(0).c_str());


  // pid_t pid;
  // pid = fork();
  // if (pid < 0) /* 如果出错 */
  // {
  //   ERROR("error occurred!\n");
  // } else if (pid == 0) /* 如果是子进程 */
  // {
  //   INFO("RUN mycapture");
  //   if (execl("./mycapture", NULL) == -1) {
  //     ERROR("EXCEL failed!\n");
  //   }
  //   exit(0);
  // }
}

void MyApplication::uninitialize() {
  // wait(NULL);
  google::ShutdownGoogleLogging();
  Util::Application::uninitialize(); //帮我们关闭子系统，必须显示的调用。
}

void MyApplication::defineOptions(Util::OptionSet &options) {
  Util::Application::defineOptions(options); //必须调用
  options.addOption(
      Util::Option("help", "h",
                   "display help information on command line arguments")
          .required(false)
          .repeatable(false)
          .callback(Util::OptionCallback<MyApplication>(
              this, &MyApplication::handleHelp)));
  options.addOption(Util::Option("daemon", "", "Run application as a daemon.")
                        .required(false)
                        .repeatable(false)
                        .callback(Util::OptionCallback<MyApplication>(
                            this, &MyApplication::handleDaemon)));
}

void MyApplication::handleHelp(const std::string &name,
                               const std::string &value) {
  m_helpRequested = true;
  Poco::Util::HelpFormatter helpFormatter(options());
  helpFormatter.format(std::cout);
}

void MyApplication::handleDaemon(const std::string &name,
                                 const std::string &value) {
  beDaemon();
}

void MyApplication::beDaemon() {
  pid_t pid;
  if ((pid = fork()) < 0)
    throw SystemException("cannot fork daemon process");
  else if (pid != 0)
    exit(0);

  setsid();
  umask(0);

  FILE *fin = freopen("/dev/null", "r+", stdin);
  if (!fin)
    throw Poco::OpenFileException("Cannot attach stdin to /dev/null");
  FILE *fout = freopen("/dev/null", "r+", stdout);
  if (!fout)
    throw Poco::OpenFileException("Cannot attach stdout to /dev/null");
  FILE *ferr = freopen("/dev/null", "r+", stderr);
  if (!ferr)
    throw Poco::OpenFileException("Cannot attach stderr to /dev/null");
}

int MyApplication::main(const std::vector<std::string> &args) {
  if (!m_helpRequested) {
    std::cout << "initialize application successful" << std::endl;
    runtask(args);
  } else {
    std::cout << "this is main call help\n";
  }
  return Application::EXIT_OK;
}

#endif